<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
	/**
	 * CodeIgniter
	 *
	 * An open source application development framework for PHP 4.3.2 or newer
	 *
	 * @package		CodeIgniter
	 * @author		ExpressionEngine Dev Team
	 * @copyright	Copyright (c) 2008 - 2009, EllisLab, Inc.
	 * @license		http://codeigniter.com/user_guide/license.html
	 * @link		http://codeigniter.com
	 * @since		Version 1.0
	 * @filesource
	 */
	// ------------------------------------------------------------------------
	
	/**
	 * @package		CodeIgniter
	 * @subpackage	Libraries
	 * @author		AnhDT
	 */
	require_once APP_LIBRARY_PATH . 'tree/menu/parser/st_menu_xml_parse_interface.php'; 
	require_once APP_LIBRARY_PATH . 'tree/menu/parser/st_menu_abstract_parser.php'; 
	require_once APP_LIBRARY_PATH . 'tree/menu/parser/st_menu_query_parser.php'; 
	class st_menu_xml_parser extends st_menu_abstract_parser implements st_menu_xml_parser_interface {
		
		/**File nguồn xml*/
		protected $_xml       = '';
		/**SimpleXMLElement Document*/
		protected $_doc       = null;
		
		/**Hàm khởi tạo*/
		public function __construct($_xml = '') {
			$this->loadXML($_xml);
		}
		
		/**Phân giải xml thành cấu trúc cây và xây dựng quan hệ cha con trong menu */
		public function parseXML($_xml) {
			if ($_xml != $this->_xml) {
				$this->loadXML($_xml);	
			}
			$_doc  = & $this->_doc;
			$_menu = & $this->getMenu();
			$_menu->resetChildren();
			// Thiết lập các thông tin
			$_attributes = array('id', 'title', 'name', 'url', 'tooltip', 'icon');
			foreach ($_attributes as $_attribute) {
				if (isset($_doc->$_attribute)) {
					$_method = 'set' . ucfirst($_attribute);
					if (method_exists($_menu, $_method)) {
						$_menu->$_method((string)$_doc->$_attribute);
					}						
				}
			}
			// Sử dụng nạp cấu trúc menu ở một file xml khác
			if  (count($_doc->children->import) > 0) {
				// Khởi tạo bộ parser mới để dùng
				$_parserXML   = new $this();
				if (!class_exists('st_menu_query_parser')) {
					$CI = & get_instance();
					$CI->load->library('tree/menu/parser/st_menu_query_parser');
					unset($CI);
				}
				$_parserQuery = new st_menu_query_parser(); 
				foreach ($_doc->children->import as $_importer) {
					if (!isset($_importer->type) || !isset($_importer->params->param)) {
						continue;	
					}
					switch ($_importer->type) {
						case 'simple_xml_data':
							foreach ($_importer->params->param as $_param) {
								$_menuImported = new st_menu();
								$this->parseConstant($_param);
								if (file_exists($_param)) {
									// Phân giải file xml
									$_parserXML->setMenu($_menuImported)
										       ->parseXML((string)$_param)
											   ->reset();
									if ($_menuImported->getId()) {
										$_menu->addChild($_menuImported);		
									}
								}
							}
						break;
						case 'simple_query_data':
							$_queries = $_importer->queries->query;
							if (isset($_queries)) {
								foreach ($_queries as $_query) {
									$_menuImported = new st_menu();
									// Phân giải câu lệnh sql
									$_content        = & $_query->content;
									$_privateKeyName = & $_query->privateKeyName;
									$_parentKeyName  = & $_query->parentKeyName;
									if (!isset($_content) || !isset($_privateKeyName) || !isset($_parentKeyName)) {
										continue;	
									}
									$_parserQuery->setMenu($_menuImported)
												 ->factory($_content, $_privateKeyName, $_parentKeyName)
										         ->parseQuery()
											     ->reset();
									if ($_menuImported->countChildren() > 0) {
										$_menu->addChild($_menuImported->getFirstChild());		
									}
								}
							}
						break;
						default:
							continue;
						break;
					}
				}
				unset($_parserXML, $_parserQuery);
			}
			if (count($_doc->children->menu) > 0) {
				foreach ($_doc->children->menu as $_item) {
					$_child = new st_menu();
					foreach ($_item as $_attribute => $_item) {
						switch ($_attribute) {
							// Xử lý thêm menu con
							case 'children':
								foreach ($_item as $_childXML) {
									$this->addRecursiveChildren($_child, $_childXML);
								}
							break;
							// Xử lý thiết lập các thông tin
							default:
								$_method = 'set' . ucfirst($_attribute);
								if (!method_exists($_child, $_method)) {
									continue;
								}
								$_child->$_method((string)$_item);
							break;
						}
						if ($_child->getName() === '') {
							$_child->setName(str_replace(' ', '_', $_child->getTitle()));
						}
					}
					if ($_child->getTitle() !== '') {
						$_menu->addChild($_child);
					}
				}
			}
			return $this;
		}
		/**Thêm đệ quy các menu con vào 1 menu theo cấu trúc xml*/
		public function addRecursiveChildren(st_menu & $_menu, $_simpleXmlObject) {
			$_child = new st_menu();
			// Thiết lập các thông tin
			if ($_simpleXmlObject->getName() === 'import') {
				$_type   = $_simpleXmlObject->type;
				if (!empty($_type)) {
					switch ($_type) {
						case 'simple_xml_data':
							$_params = $_simpleXmlObject->params->param;
							if (!empty($_params)) {
								$_parserXML = new $this();
								foreach ($_params as $_param) {
									$_menuImported = new st_menu();
									$this->parseConstant($_param);
									if (file_exists($_param)) {
										$_parserXML->setMenu($_menuImported)
												   ->parseXML((string)$_param)
												   ->reset();
										if ($_menuImported->getId()) {
											$_menu->addChild($_menuImported);		
										}
									}	
								}
								unset($_parserXML, $_params);
							}
						break;
						case 'simple_query_data':
							$_queries = $_simpleXmlObject->queries->query;
							if (isset($_queries)) {
								$_parserQuery = new st_menu_query_parser(); 
								foreach ($_queries as $_query) {
									$_menuImported = new st_menu();
									// Phân giải câu lệnh sql
									$_content        = & $_query->content;
									$_privateKeyName = & $_query->privateKeyName;
									$_parentKeyName  = & $_query->parentKeyName;
									if (!isset($_content) || !isset($_privateKeyName) || !isset($_parentKeyName)) {
										continue;	
									}
									$_parserQuery->setMenu($_menuImported)
												 ->factory($_content, $_privateKeyName, $_parentKeyName)
										         ->parseQuery()
											     ->reset();
									if ($_menuImported->countChildren() > 0) {
										$_menu->addChild($_menuImported->getFirstChild());		
									}
								}
							}
							unset($_parserQuery, $_queries);
						break;
					}
				}
			}
			foreach ($_simpleXmlObject as $_attribute => $_item) {
				switch ($_attribute) {
					case 'children':
						foreach ($_item as $_childXML) {
							$this->addRecursiveChildren($_child, $_childXML);
						}
					break;
					default:
						$_method = 'set' . ucfirst($_attribute);
						if (!method_exists($_child, $_method)) {
							continue;
						}
						$_child->$_method((string)$_item);
					break;
				}
			}
			if ($_child->getTitle() !== '') {
				$_menu->addChild($_child);
			}
			return $this;
		}
		
		/**Nạp file xml*/
		public function loadXML($_xml = '') {
			if (!file_exists($_xml)) {
				return false;	
			}
			$this->_doc = simplexml_load_file($_xml);
			if (empty($this->_doc)) {		
				$this->_loaded = false;
				return false;
			} 
			$this->_xml    = $_xml;
			$this->_loaded = true;
			return $this;
		}
		
		/**Lấy về đối tượng SimpleXMLDocument gốc*/
		public function getDocument() {
			return $this->_doc;	
		}
		
		/**Reset lại toàn bộ thông tin*/
		public function reset() {
			parent::reset();
			$this->_xml = '';
			$this->_doc = null;	
			return $this;
		}
		
		/**Phân giải hằng*/
		public function parseConstant(& $_param) {
			$_param = & preg_replace_callback("/{{(.*)}}/",
			create_function(
				'$matches',
				'return constant($matches[1]);'
			), $_param);
			return $this;
		}
	}
?>